/*
zigbee.c
offer zigbee conmunication driver
designed by lunanting

-------------------------
2020-07-05 12:22:31
create file
-------------------------


*/

#include "zigbee.h"
#ifdef OK1054W
#include "../../../board/ok1054w/board/wlt3048nz.h"
#include "../../../board/ok1054w/board/board.h"
#else
#include "../../../board/ok1053w/board/wlt3048nz.h"
#include "../../../board/ok1053w/board/board.h"
#endif
#include "aos/kernel.h"
#include "stdarg.h"
#include "bsp.h"

static char format_buf[101];

static ZIGBEE_class zigbee={0};
static aos_sem_t zigbee_sem;

int xp_zigbee_address_check(u16 addr);
en_workmode_t xp_zigbee_transfer_mode(ZIGBEE_mode mode);
extern uart_dev_t uart_zigbee;
void xp_zigbee_recive_deal_thread(void *arg);

/*
zigbee module init
param:
    mode:module work mode
    local_addr:local address
return:
    0=success
*/
int xp_zigbee_init(ZIGBEE_mode mode,u16 local_addr){
    gpio_dev_t io={0};
    en_workmode_t md=0;

    // if(xp_zigbee_address_check(local_addr)!=1)return -1;
    md=xp_zigbee_transfer_mode(mode);
    // io.port=PORT_GPIO_ZIGBEE_RST;
    io.config=OUTPUT_PUSH_PULL;
    io.priv=NULL;

    if(wlt3408nz_dev_init(&io,&uart_zigbee)!=0){
        println("zigbee module init fail~");
        return -2;
    }
    if(wlt3408nz_set_dev_work_mode(md)!=0){
        println("zigbee module set mode fail~");
        return -3;
    }
    if(wlt3408nz_set_local_addr(local_addr)!=0){
        println("zigbee module set local address fail~");
        return -4;
    }
    aos_sem_new(&zigbee_sem,1);
    zigbee.init=1;
    zigbee.mode=mode;
    zigbee.local_addr=local_addr;
    aos_task_t zigbee_driver;
    aos_task_new_ext(&zigbee_driver,"zigbee recive",xp_zigbee_recive_deal_thread,NULL,3000,10);
    println("zigbee module init success!");
    return 0;
}




/*
zigbee send data
param:
    target_addr:target address
    data:send data
    len:send data length
return:
    0=success
*/
int xp_zigbee_send(u16 target_addr,u8 *data,u8 len){
    int retry=3;
    u8 sendbuf[ZIGBEE_COM_BUFFER_SIZE]={0};
    memcpy(sendbuf,data,len);
    if(len >ZIGBEE_COM_BUFFER_SIZE)
    {
        println("data length exceed ZIGBEE_COM_BUFFER_SIZE 40");
        return -1;
    }
    if(zigbee.init!=1)return -3;
    // if(xp_zigbee_address_check(target_addr)==0)return -1;
    //zigbee.response=0;
    while(retry--){
        if(wlt3408nz_dev_data_send(target_addr,sendbuf,ZIGBEE_COM_BUFFER_SIZE)==0)break;
    }
    if(retry==0){
        return -2;
    }
    retry =10 ;
    while(retry--){
        if(zigbee.response==1){
            zigbee.response=0;
            return 0;
        }
        else if(zigbee.response==-1){
            zigbee.response=0;
            return 1;
        }
        aos_msleep(ZIGBEE_UART_DEFAULT_TIMEOUT);
    }
    return -4;
}

/*
zigbee module send raw data
param:
    target_addr:target address
    data:send data
    len:send data length
return:
    0=success
*/

int xp_zigbee_send_data(u16 target_addr,u8 *data,u8 len){
    int sta = 1;
    s8 count = 3;
    if(aos_sem_wait(&zigbee_sem,6000)!=0)return -1;
    while(count--)
    {
        sta=xp_zigbee_send(target_addr,data,len);
        if(sta!=0)
        {
            aos_msleep(ZIGBEE_UART_DEFAULT_TIMEOUT*5);
            printf("sta is %d \n\r",sta);
            continue;
        }
        else
        {
            break;
        }
        aos_msleep(100);
    }
    aos_sem_signal(&zigbee_sem);
    if(sta==0){
        printf("sta is %d 99\n\r",sta);
        return 0;
    }
    return -1;
}


/*
zigbee module send format string
param:
    str:format string
return:
    0=success
*/
int xp_zigbee_printf(u16 target_addr,const char *str,...){
    va_list va;
    int sta=0;
    
    if(zigbee.init!=1)return -3;
    if(aos_sem_wait(&zigbee_sem,1000)!=0)return -1;
    sprintf(format_buf,"%d:",zigbee.local_addr);
    va_start(va,str);
    vsnprintf(format_buf+strlen(format_buf),100,str,va);
    va_end(va);
    sta=xp_zigbee_send(target_addr,(u8 *)format_buf,strlen(format_buf));
    aos_sem_signal(&zigbee_sem);
    if(sta!=0){
        return -2;
    }
    return 0;
}



/*
recive data deal thread
*/
void xp_zigbee_recive_deal_thread(void *arg){
    u16 psd=0;
    char buf[ZIGBEE_COM_BUFFER_SIZE]={0},s_buf[20];
    char *key,*value,*foot;
    u16 s_addr=0;
    while(true){
        memset(buf,0,ZIGBEE_COM_BUFFER_SIZE);
        if(wlt3408nz_dev_data_recv(&psd,(u8 *)buf,ZIGBEE_COM_BUFFER_SIZE)==0)
        {
            printf("&&&&&&&&&&&&&&&&received buf is: %s 0x%x 0x%x 0x%x \n\r", buf,buf[4],buf[5],buf[6]);
            key=strtok_r(buf,":",&foot);
            value=foot;
            s_addr=atoi(key);
            /*
            if(strlen(key)<2){
                sprintf(buf,"%d:error",zigbee.local_addr);
                wlt3408nz_dev_data_send(s_addr,(u8 *)buf,strlen(buf));
            }
            */
            if(strcmp(key,"mem")==0){
               printf("<<<<<>>>>>> %x %x %x %x  <<<<<>>>>>\n\r",*value,*(value+1),*(value+2),*(value+3));
               xp_zigbee_recive_data_api((u8*)value,ZIGBEE_COM_BUFFER_SIZE-4);
            }
            else if(strcmp(value,"ok")==0){
                zigbee.response=1;
            }
            else if(strcmp(value,"error")==0){
                zigbee.response=-1;
            }
            else{
                sprintf(s_buf,"%d:ok",zigbee.local_addr);
                wlt3408nz_dev_data_send(s_addr,(u8 *)s_buf,strlen(s_buf));
                xp_zigbee_recive_string_api(value);
            }
            //memset(buf,0,ZIGBEE_COM_BUFFER_SIZE);
            
        }
        else
        {
            //printf("==========%s 0x%x 0x%x 0x%x ", buf,buf[4],buf[5],buf[6]);
        }
    }
}


/*
check address correct
param:
    addr:address
return: check result,1=correct,0=error
*/
int xp_zigbee_address_check(u16 addr){
    if(0<addr&&addr<8){
        return 1;
    }
    else{
        println("zigbee address check error,addr=%d",addr);
        return 0;
    }
}


/*
transfer zigbee mode type
param:
    mode:ZIGBEE_mode
return:en_workmode_t 
*/
en_workmode_t xp_zigbee_transfer_mode(ZIGBEE_mode mode){
    if(mode==zigbee_maste){
        return WORKMODE_HOST;
    }
    else if(mode==zigbee_terminal){
        return WORKMODE_TERMINAL;
    }
    else if(mode==zigbee_master_relay){
        return WORKMODE_HOST_RELAY;
    }
    else if(mode==zigbee_terminal_relay){
        return WORKMODE_TERMINAL_RELAY;
    }
    else {
        println("input mode error,mode=%d,reset to master mode",mode);
        return WORKMODE_HOST;
    }
}


/************************************api define ******************************/
void __weak xp_zigbee_recive_string_api(char *str){
    println("weak function,string:%s",str);
}

void __weak xp_zigbee_recive_data_api(u8 *data,u8 len){
    println("weak function,data[%d]:%d,%d,%d",len,data[0],data[1],data[2]);
}

/*******************************debug************************/
static u16 debug_target_addr=0;
/*
zigbee debug
*/
int xp_zigbee_debug(char *type,char *fun,char *param){

    uint16_t temfaddr = 0;
    uint8_t wmode = 0;
    int ret = 0;
    uint8_t data[ZIGBEE_COM_BUFFER_SIZE] = "zig1234z";
    if(strcmp(type,"zigbee")!=0)return 0;
    if(strcmp(fun,"target_addr")==0){
        debug_target_addr=atoi(param);
		println("set target_addr is %d ",debug_target_addr);
		ret = wlt3408nz_set_dest_addr(debug_target_addr);
        if(ret != 0)
        {
            println("set target_addr zigbee address fail!");
            return 1;
        }
        println("target_addr is %d sucess",debug_target_addr);
    }
    else if(strcmp(fun,"send")==0){
        temfaddr=atoi(param);
        println("temfaddr is  %d \n\r",temfaddr);
        xp_zigbee_send_data(temfaddr,data,10);
    }
    else if(strcmp(fun,"localaddr")==0)
    {
        ret = wlt3408nz_get_local_addr(&temfaddr);
        if(ret != 0)
        {
            println("get local zigbee address fail!");
            return 1;
        }
        println("localaddr is %d ",temfaddr);
    }
    else if(strcmp(fun,"setaddrl")==0)
    {
        temfaddr = strtoul(param, NULL, 10);
        println("set zigbee local address is %d",temfaddr);
        ret = wlt3408nz_set_local_addr(temfaddr);
        if(ret != 0)
        {
            println("set local address fail ");
            return 1;
        }
        println("set zigbee local address is %d and success !!!",temfaddr);
    }
    else if(strcmp(fun,"wmode")==0)
    {
        ret = wlt3408nz_get_dev_work_mode(&wmode);
        if(ret != 0)
        {
            println("get local zigbee work mode fail!");
            return 1;
        }
        println("mode is %d ",wmode);
    }
    else if(strcmp(fun,"destaddr")==0)
    {
        ret = wlt3408nz_get_dest_addr(&temfaddr);
        if(ret != 0)
        {
            println("get dest address  fail!");
            return 1;
        }
        println("get destaddr is %d ",temfaddr);
    }
    else{
        return 0;
    }
    return 1;
}

//end of the file
